package com.video.commons.runtimelog;

import com.qf.entity.RunLogEntity;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * 该类用于记录日志，
 * Controller -> Service -> Dao 每层日志依次记录
 */
@Aspect
//@Component
@Slf4j
@Order(200)
public class RunLogAop {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 拦截所有controller
     * @param proceedingJoinPoint
     * @return
     */
    @Around("execution(* com.video.controller..*.*(..)) || execution(* com.video.service..*.*(..)) || execution(* com.video.mapper.*.*(..))")
    public Object runLogControl(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //运行日志实体类
        RunLogEntity runLogEntity = new RunLogEntity();

        runLogEntity.setRequestId(RequestIdThreadLocal.getId());
        runLogEntity.setOrder(RequestIdThreadLocal.getNumber());

        //请求的url
        //获得请求
        if(RequestContextHolder.getRequestAttributes() != null){
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            String url = request.getRequestURL().toString();
            runLogEntity.setUrl(url);
        }


        //当前类
        String className = proceedingJoinPoint.getTarget().getClass().getName();
        runLogEntity.setClassName(className);

        //获得方法名称
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        String name = method.getName();
        runLogEntity.setMethodName(name);

        //获得方法形式参数
        Parameter[] parameters = method.getParameters();

        //获得所有形式参数
        Object[] args = proceedingJoinPoint.getArgs();
        if(args != null){
            for (int i = 0; i < args.length; i++) {
                runLogEntity.putParams(parameters[i].getName(), args[i] != null ? args[i].toString() : null);
            }
        }

        //调用目标方法
        Object result;
        try {
            result = proceedingJoinPoint.proceed();
            runLogEntity.setResult(result != null ? result.toString() : null);
        } catch (Throwable throwable) {
            //记录当前异常
            runLogEntity.setThrowInfo(throwable);
            //异常继续上抛
            throw throwable;
        } finally {
            //将运行日志信息保存到日志存储栈中
            if(RequestIdThreadLocal.isLog()) {
                RunLogUtil.runLog(rabbitTemplate, runLogEntity);
            }
        }

        //返回结果
        return result;
    }
}
